using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using DG.Tweening;
using UnityEngine;

public class ElevatorController : MonoBehaviour
{
    [Header("电梯轿厢")]
    [SerializeField] Transform elevatorCar;
    [SerializeField] Transform[] doors;
    private PlayerController playerController;
    private ElevatorCarController elevatorCarController;

    [Header("电梯停留时间，单位：秒")]
    public int dwellTime = 5;
    [Header("电梯运行速度")]
    [Tooltip("此值越大电梯运行越慢")]
    public int movementSpeed = 2;
    /// <summary>
    /// doors的索引集合
    /// </summary>
    private int[] indexes;
    private float distanceMovedDoor = 10;
    /// <summary>
    /// 电梯开关时间，单位：秒
    /// </summary>
    private int openTimeDoor = 1;

    /// <summary>
    /// 当前楼层
    /// </summary>
    public int CurrentFloor { get; set; } = 1;
    /// <summary>
    /// 电梯状态
    /// </summary>
    public ElevatorStatus ElevatorStatus { get; set; }

    void Awake()
    {
        this.indexes = new int[this.doors.Length];
        for (int i = 0; i < this.doors.Length; i++)
        {
            this.indexes[i] = i;
        }
        // this.playerController = FindObjectOfType<PlayerController>(); // 旧方法[obsolete]
        this.playerController = FindFirstObjectByType<PlayerController>();
        this.elevatorCarController = this.elevatorCar.GetComponent<ElevatorCarController>();
    }

    void Start()
    {
        StartCoroutine(nameof(Working));
    }

    IEnumerator Working()
    {
        int currentIndex = 0;
        int interval = this.movementSpeed + this.dwellTime;

        while (true)
        {
            var currentDoor = this.doors[currentIndex];
            var nextIndex = GetNextIndex(currentIndex);
            var nextDoor = this.doors[nextIndex];
            // 楼层高度
            var distanceY = nextDoor.localPosition.y - currentDoor.localPosition.y;
            this.elevatorCar.DOLocalMoveY(this.elevatorCar.localPosition.y + distanceY, this.movementSpeed)
            .OnStart(() =>
            {
                this.ElevatorStatus = ElevatorStatus.Moving;
                this.PreventJolt();
            })
            .SetEase(Ease.InOutQuad).OnComplete(() =>
            {
                this.ElevatorStatus = ElevatorStatus.Boarding;
                this.CurrentFloor = nextIndex + 1;
                // 开门
                nextDoor.DOLocalMoveX(nextDoor.localPosition.x + this.distanceMovedDoor, this.openTimeDoor).OnComplete(() =>
                {
                    // 关门
                    nextDoor.DOLocalMoveX(nextDoor.localPosition.x - this.distanceMovedDoor, this.openTimeDoor)
                    .SetDelay(this.dwellTime - 2 * this.openTimeDoor)
                    .OnComplete(() =>
                    {

                    });
                });
                this.PreventJolt();
            });
            currentIndex = nextIndex;
            yield return new WaitForSeconds(interval);
        }
    }

    /// <summary>
    /// 按索引顺序从indexes中取值，每次到末尾后翻转indexes
    /// 会依次得到0，1，2，3，2，1，0，1，2，3，2，1，0...
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    private int GetNextIndex(int value)
    {
        if (value == this.indexes.Last())
        {
            this.indexes = this.indexes.Reverse().ToArray();
            return this.indexes[1];
        }
        var next = this.indexes[Array.IndexOf(this.indexes, value) + 1];
        return next;
    }

    /// <summary>
    /// 是否上升
    /// </summary>
    /// <returns></returns>
    public bool IsLifting()
    {
        if (this.indexes[0] > this.indexes[1])
        {
            return false;
        }
        return true;
    }

    /// <summary>
    /// 电梯运行中防止乘客颠簸
    /// </summary>
    private void PreventJolt()
    {
        if (this.elevatorCarController.Transforms.Count() > 0)
        {
            Debug.Log("PreventJolt");
            this.elevatorCarController.Transforms.ForEach(x =>
            {
                x.transform.SetParent(this.ElevatorStatus == ElevatorStatus.Moving ? this.elevatorCar : null);
                switch (x.tag)
                {
                    case Defines.Player:
                        this.playerController.Status =
                        (this.ElevatorStatus == ElevatorStatus.Moving) ? PlayerStatus.Locked : PlayerStatus.Normal;
                        break;
                }
            });
        }
    }

    void OnDestroy()
    {
        StopAllCoroutines();
    }
}
